1 /*
2 * Copyright (C) 2011 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5 * in compliance with the License. You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software distributed under the
10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11 * express or implied. See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 package com.google.common.primitives;
16
17 import static com.google.common.base.Preconditions.checkArgument;
18 import static com.google.common.base.Preconditions.checkNotNull;
19 import static com.google.common.primitives.UnsignedInts.INT_MASK;
20 import static com.google.common.primitives.UnsignedInts.compare;
21 import static com.google.common.primitives.UnsignedInts.toLong;
22
23 import com.google.common.annotations.GwtCompatible;
24 import com.google.common.annotations.GwtIncompatible;
25
26 import java.math.BigInteger;
27
28 import javax.annotation.CheckReturnValue;
29 import javax.annotation.Nullable;
30
31 /**
32 * A wrapper class for unsigned {@code int} values, supporting arithmetic operations.
33 *
34 * <p>In some cases, when speed is more important than code readability, it may be faster simply to
35 * treat primitive {@code int} values as unsigned, using the methods from {@link UnsignedInts}.
36 *
37 * <p>See the Guava User Guide article on <a href=
38 * "http://code.google.com/p/guava-libraries/wiki/PrimitivesExplained#Unsigned_support">
39 * unsigned primitive utilities</a>.
40 *
41 * @author Louis Wasserman
42 * @since 11.0
43 */
44 @GwtCompatible(emulated = true)
45 public final class UnsignedInteger extends Number implements Comparable<UnsignedInteger> {
46 public static final UnsignedInteger ZERO = fromIntBits(0);
47 public static final UnsignedInteger ONE = fromIntBits(1);
48 public static final UnsignedInteger MAX_VALUE = fromIntBits(-1);
49
50 private final int value;
51
52 private UnsignedInteger(int value) {
53 // GWT doesn't consistently overflow values to make them 32-bit, so we need to force it.
54 this.value = value & 0xffffffff;
55 }
56
57 /**
58 * Returns an {@code UnsignedInteger} corresponding to a given bit representation.
59 * The argument is interpreted as an unsigned 32-bit value. Specifically, the sign bit
60 * of {@code bits} is interpreted as a normal bit, and all other bits are treated as usual.
61 *
62 * <p>If the argument is nonnegative, the returned result will be equal to {@code bits},
63 * otherwise, the result will be equal to {@code 2^32 + bits}.
64 *
65 * <p>To represent unsigned decimal constants, consider {@link #valueOf(long)} instead.
66 *
67 * @since 14.0
68 */
69 public static UnsignedInteger fromIntBits(int bits) {
70 return new UnsignedInteger(bits);
71 }
72
73 /**
74 * Returns an {@code UnsignedInteger} that is equal to {@code value},
75 * if possible. The inverse operation of {@link #longValue()}.
76 */
77 public static UnsignedInteger valueOf(long value) {
78 checkArgument((value & INT_MASK) == value,
79 "value (%s) is outside the range for an unsigned integer value", value);
80 return fromIntBits((int) value);
81 }
82
83 /**
84 * Returns a {@code UnsignedInteger} representing the same value as the specified
85 * {@link BigInteger}. This is the inverse operation of {@link #bigIntegerValue()}.
86 *
87 * @throws IllegalArgumentException if {@code value} is negative or {@code value >= 2^32}
88 */
89 public static UnsignedInteger valueOf(BigInteger value) {
90 checkNotNull(value);
91 checkArgument(value.signum() >= 0 && value.bitLength() <= Integer.SIZE,
92 "value (%s) is outside the range for an unsigned integer value", value);
93 return fromIntBits(value.intValue());
94 }
95
96 /**
97 * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
98 * as an unsigned {@code int} value.
99 *
100 * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
101 * value
102 */
103 public static UnsignedInteger valueOf(String string) {
104 return valueOf(string, 10);
105 }
106
107 /**
108 * Returns an {@code UnsignedInteger} holding the value of the specified {@code String}, parsed
109 * as an unsigned {@code int} value in the specified radix.
110 *
111 * @throws NumberFormatException if the string does not contain a parsable unsigned {@code int}
112 * value
113 */
114 public static UnsignedInteger valueOf(String string, int radix) {
115 return fromIntBits(UnsignedInts.parseUnsignedInt(string, radix));
116 }
117
118 /**
119 * Returns the result of adding this and {@code val}. If the result would have more than 32 bits,
120 * returns the low 32 bits of the result.
121 *
122 * @since 14.0
123 */
124 @CheckReturnValue
125 public UnsignedInteger plus(UnsignedInteger val) {
126 return fromIntBits(this.value + checkNotNull(val).value);
127 }
128
129 /**
130 * Returns the result of subtracting this and {@code val}. If the result would be negative,
131 * returns the low 32 bits of the result.
132 *
133 * @since 14.0
134 */
135 @CheckReturnValue
136 public UnsignedInteger minus(UnsignedInteger val) {
137 return fromIntBits(value - checkNotNull(val).value);
138 }
139
140 /**
141 * Returns the result of multiplying this and {@code val}. If the result would have more than 32
142 * bits, returns the low 32 bits of the result.
143 *
144 * @since 14.0
145 */
146 @CheckReturnValue
147 @GwtIncompatible("Does not truncate correctly")
148 public UnsignedInteger times(UnsignedInteger val) {
149 // TODO(user): make this GWT-compatible
150 return fromIntBits(value * checkNotNull(val).value);
151 }
152
153 /**
154 * Returns the result of dividing this by {@code val}.
155 *
156 * @throws ArithmeticException if {@code val} is zero
157 * @since 14.0
158 */
159 @CheckReturnValue
160 public UnsignedInteger dividedBy(UnsignedInteger val) {
161 return fromIntBits(UnsignedInts.divide(value, checkNotNull(val).value));
162 }
163
164 /**
165 * Returns this mod {@code val}.
166 *
167 * @throws ArithmeticException if {@code val} is zero
168 * @since 14.0
169 */
170 @CheckReturnValue
171 public UnsignedInteger mod(UnsignedInteger val) {
172 return fromIntBits(UnsignedInts.remainder(value, checkNotNull(val).value));
173 }
174
175 /**
176 * Returns the value of this {@code UnsignedInteger} as an {@code int}. This is an inverse
177 * operation to {@link #fromIntBits}.
178 *
179 * <p>Note that if this {@code UnsignedInteger} holds a value {@code >= 2^31}, the returned value
180 * will be equal to {@code this - 2^32}.
181 */
182 @Override
183 public int intValue() {
184 return value;
185 }
186
187 /**
188 * Returns the value of this {@code UnsignedInteger} as a {@code long}.
189 */
190 @Override
191 public long longValue() {
192 return toLong(value);
193 }
194
195 /**
196 * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
197 * primitive conversion from {@code int} to {@code float}, and correctly rounded.
198 */
199 @Override
200 public float floatValue() {
201 return longValue();
202 }
203
204 /**
205 * Returns the value of this {@code UnsignedInteger} as a {@code float}, analogous to a widening
206 * primitive conversion from {@code int} to {@code double}, and correctly rounded.
207 */
208 @Override
209 public double doubleValue() {
210 return longValue();
211 }
212
213 /**
214 * Returns the value of this {@code UnsignedInteger} as a {@link BigInteger}.
215 */
216 public BigInteger bigIntegerValue() {
217 return BigInteger.valueOf(longValue());
218 }
219
220 /**
221 * Compares this unsigned integer to another unsigned integer.
222 * Returns {@code 0} if they are equal, a negative number if {@code this < other},
223 * and a positive number if {@code this > other}.
224 */
225 @Override
226 public int compareTo(UnsignedInteger other) {
227 checkNotNull(other);
228 return compare(value, other.value);
229 }
230
231 @Override
232 public int hashCode() {
233 return value;
234 }
235
236 @Override
237 public boolean equals(@Nullable Object obj) {
238 if (obj instanceof UnsignedInteger) {
239 UnsignedInteger other = (UnsignedInteger) obj;
240 return value == other.value;
241 }
242 return false;
243 }
244
245 /**
246 * Returns a string representation of the {@code UnsignedInteger} value, in base 10.
247 */
248 @Override
249 public String toString() {
250 return toString(10);
251 }
252
253 /**
254 * Returns a string representation of the {@code UnsignedInteger} value, in base {@code radix}.
255 * If {@code radix < Character.MIN_RADIX} or {@code radix > Character.MAX_RADIX}, the radix
256 * {@code 10} is used.
257 */
258 public String toString(int radix) {
259 return UnsignedInts.toString(value, radix);
260 }
261 }